﻿using System;
using System.Collections.Generic;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine.Core.Interface;
using RayDen.RayEngine.Core.Surface;
using RayDen.RayEngine.Core.Types;

namespace RayDen.RayEngine.Data
{
    public class TriangleMesh : ITriangleMesh
    {
        public string MeshName { get; set; }
        public string MaterialName { get; set; }
        public int[] Indexes;
        public Dictionary<int, Normal[]> normals;
        public Dictionary<int, UV[]> texCoords;

        public bool HasNormals { get; set; }
        public bool HasTexCoords { get; set; }

        public GeometryProfile MeshProfile { get; set; }

        public RayEngineMaterial Material
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public int MaterialID
        {
            get;
            set;
        }

        public float MeshArea;

        public TriangleMesh()
        {
            normals = new Dictionary<int, Normal[]>(300);
            texCoords = new Dictionary<int, UV[]>();
            MeshProfile = new SurfaceProfile();
        }


        public int EndVertice, StartVertice, VerticesOffset;

        public int StartTriangle { get; set; }
        public int EndTriangle { get; set; }


        public bool TriangleInRange(int triIndex, int delta = 0)
        {
            var start = triIndex != 0 ? StartTriangle + delta : triIndex;
            var end = Math.Max(0, EndTriangle - delta);

            return (triIndex <= (end) && triIndex >= start);
        }

        public void InterpolateTriUV(int currentTriangleIndex, float b1, float b2, out UV texCoord)
        {
            var triIndex = currentTriangleIndex;
            if (texCoords == null || texCoords.Count == 0)
                texCoord = new UV { U = b1, V = b2 };
            else
            {
                var t0 = texCoords[triIndex][0];
                var t1 = texCoords[triIndex][1];
                var t2 = texCoords[triIndex][2];
                float b0 = 1f - b1 - b2;

                //            return t0 * b1 + t1 * b2 + t2 * b0;
                texCoord = new UV(t0.U*b0 + t1.U*b1 + t2.U*b2, t0.V*b0 + t1.V*b1 + t2.V*b2);
            }
        }

        public void InterpolateTriangleNormal(int currentTriangleIndex, float b1, float b2, ref Normal Normal)
        {
            var triIndex = currentTriangleIndex;

            var n0 = normals[triIndex][0];
            var n1 = normals[triIndex][1];
            var n2 = normals[triIndex][2];

            float b0 = 1f - b1 - b2;
            Normal = new Normal(b0 * n0.x + b1 * n1.x + b2 * n2.x,
                              b0 * n0.y + b1 * n1.y + b2 * n2.y,
                              b0 * n0.z + b1 * n1.z + b2 * n2.z).Normalize();
            //return b0 * n0 + b1 * n1 + b2 * n2;
        }

        public int TrianglesCount { get { return EndTriangle - StartTriangle; } }
    }
}